#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion

using System;
using System.Collections.Generic;
using System.Net.Mail;
using Moq;
using Newtonsoft.Utilities.Email;
using Newtonsoft.Utilities.Miscellaneous;
using Newtonsoft.Utilities.Testing;
using Newtonsoft.Utilities.IO;
using NUnit.Framework;

namespace Newtonsoft.Utilities.Tests.Email
{
  public class EmailControllerTests : TestsBase
  {
    [Test]
    public void Simple()
    {
      var mockEmailSender = new Mock<IEmailSender>();
      mockEmailSender.Expect(s => s.SendMail(It.IsAny<MailMessage>()))
        .Callback<MailMessage>(message =>
                               {
                                 Assert.AreEqual("james.newtonking@newtonsoft.com", message.From.Address);
                                 Assert.AreEqual(1, message.To.Count);
                                 Assert.AreEqual("test@test.com", message.To[0].Address);
                                 Assert.AreEqual("Test subject", message.Subject);
                                 Assert.AreEqual("Test body.", message.Body);
                                 Assert.AreEqual(0, message.CC.Count);
                                 Assert.AreEqual(0, message.Bcc.Count);
                                 Assert.AreEqual(0, message.Attachments.Count);
                                 Assert.AreEqual(MailPriority.Normal, message.Priority);
                                 Assert.AreEqual(false, message.IsBodyHtml);
                               });

      EmailController emailController = new EmailController(null, new MailAddress("james.newtonking@newtonsoft.com"), null, true);
      emailController.EmailSender = mockEmailSender.Object;

      emailController.SendEmail(null, EmailUtils.ParseEmailAddresses("test@test.com"), "Test subject", "Test body.", false, new List<Attachment>());
    }

    [Test]
    public void Template()
    {
      var mockEmailSender = new Mock<IEmailSender>();
      mockEmailSender.Expect(s => s.SendMail(It.IsAny<MailMessage>()))
        .Callback<MailMessage>(message =>
                               {
                                 Assert.AreEqual("james.newtonking@newtonsoft.com", message.From.Address);
                                 Assert.AreEqual(1, message.To.Count);
                                 Assert.AreEqual("test@test.com", message.To[0].Address);
                                 Assert.AreEqual("Test subject - This is test param string", message.Subject);
                                 Assert.AreEqual(@"<html><body><p>
          TestParamString: This is test param string<br />
          TestParamInteger: 42</p></body></html>",
                                                 message.Body);
                                 Assert.AreEqual(0, message.CC.Count);
                                 Assert.AreEqual(0, message.Bcc.Count);
                                 Assert.AreEqual(0, message.Attachments.Count);
                                 Assert.AreEqual(MailPriority.Normal, message.Priority);
                                 Assert.AreEqual(true, message.IsBodyHtml);
                               });

        EmailController emailController = new EmailController(null, new MailAddress("james.newtonking@newtonsoft.com"), null, true);
        emailController.EmailSender = mockEmailSender.Object;

        string templatePath = FileUtils.MapPath("~/Email/TestTemplate.xslt");

        IDictionary<string, object> parameters = new Dictionary<string, object>();
        parameters.Add("TestParamString", "This is test param string");
        parameters.Add("TestParamInteger", 42);

        emailController.SendEmail(null, EmailUtils.ParseEmailAddresses("test@test.com"), templatePath, parameters, new List<Attachment>());
    }

    [Test]
    public void OverrideEmailAddress()
    {
      var mockEmailSender = new Mock<IEmailSender>();
      mockEmailSender.Expect(s => s.SendMail(It.IsAny<MailMessage>()))
        .Callback<MailMessage>(message =>
                               {
                                 Assert.AreEqual("james.newtonking@newtonsoft.com", message.From.Address);
                                 Assert.AreEqual(1, message.To.Count);
                                 Assert.AreEqual("override@test.com", message.To[0].Address);
                                 Assert.AreEqual("Test subject (Message intended for: test@test.com)", message.Subject);
                                 Assert.AreEqual("Test body.", message.Body);
                                 Assert.AreEqual(0, message.CC.Count);
                                 Assert.AreEqual(0, message.Bcc.Count);
                                 Assert.AreEqual(0, message.Attachments.Count);
                                 Assert.AreEqual(MailPriority.Normal, message.Priority);
                                 Assert.AreEqual(true, message.IsBodyHtml);
                               });

      EmailController emailController = new EmailController(EmailUtils.ParseEmailAddresses("override@test.com"), new MailAddress("james.newtonking@newtonsoft.com"), null, true);
      emailController.EmailSender = mockEmailSender.Object;

      emailController.SendEmail(null, EmailUtils.ParseEmailAddresses("test@test.com"), "Test subject", "Test body.", true, new List<Attachment>());
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"No fromEmailAddress specified and no default from email address was given to the EmailController.
Parameter name: fromEmailAddress")]
    public void EmailControllerNullFromAddressNoDefaultDefined()
    {
      EmailController emailController = new EmailController(null, null, null, true);
      emailController.EmailSender = new Mock<IEmailSender>().Object;

      emailController.SendEmail(null, EmailUtils.ParseEmailAddresses("test@test.com"), "Test subject", "Test body.", true, new List<Attachment>());
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null.
Parameter name: toEmailAddresses")]
    public void EmailControllerNullToAddresses()
    {
      EmailController emailController = new EmailController(null, null, null, true);
      emailController.EmailSender = new Mock<IEmailSender>().Object;

      emailController.SendEmail(new MailAddress("james.newtonking@newtonsoft.com"), null, "Test subject", "Test body.", true, new List<Attachment>());
    }

    [Test]
    [ExpectedException(typeof(ArgumentException), ExpectedMessage = @"No to email address(es) provided.
Parameter name: toEmailAddresses")]
    public void EmailControllerEmptyToAddresses()
    {
      EmailController emailController = new EmailController(null, null, null, true);
      emailController.EmailSender = new Mock<IEmailSender>().Object;

      emailController.SendEmail(new MailAddress("james.newtonking@newtonsoft.com"), new MailAddressCollection(), "Test subject", "Test body.", true, new List<Attachment>());
    }

    [Test]
    [ExpectedException(typeof(InvalidOperationException), ExpectedMessage = @"No email sender set on controller.")]
    public void EmailControllerNoEmailSender()
    {
      EmailController emailController = new EmailController(null, null, null, true);

      emailController.SendEmail(new MailAddress("james.newtonking@newtonsoft.com"), EmailUtils.ParseEmailAddresses("test@test.com"), "Test subject", "Test body.", true, new List<Attachment>());
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null.
Parameter name: xslTemplatePath")]
    public void EmailControllerNullTemplate()
    {
      EmailController emailController = new EmailController(null, null, null, true);
      emailController.SendEmail(null, null, new Dictionary<string, object>());
    }

    [Test]
    [ExpectedException(typeof(ArgumentException), ExpectedMessage = @"'xslTemplatePath' cannot be empty.
Parameter name: xslTemplatePath")]
    public void EmailControllerEmptyTemplate()
    {
      EmailController emailController = new EmailController(null, null, null, true);
      emailController.SendEmail(null, string.Empty, new Dictionary<string, object>());
    }
  }
}